package de.rj.urwalking.ui.fragments;

import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ImageButton;

import com.actionbarsherlock.app.SherlockFragment;

import de.rj.urwalking.R;
import de.rj.urwalking.config.Config;
import de.rj.urwalking.config.Constants;
import de.rj.urwalking.util.Util;

/**
 * 
 * @author rjj
 *
 */
public class OrientationCheckFragment extends SherlockFragment implements SensorEventListener {

	private static final String TAG = Config.TAG;
	private static final boolean DEBUG = Config.DEBUG;

	OnOrientationConfirmedListener mCallback;

	private SensorManager mSensorManager;
	private Sensor mSensorAccelerometer;
	private Sensor mSensorMagneticField;
	private float[] accelData;
	private float[] magnetData;
	private float azimuth;
	private float smoothingFactor;
	private long startTimestamp;

	// Container Activity must implement this interface
	public interface OnOrientationConfirmedListener {
		public void onOrientationConfirmed(float orientation, long startTimestamp, long endTimestamp);
	}

	@Override
	public void onAttach(Activity activity) {
		super.onAttach(activity);

		startTimestamp = System.currentTimeMillis();

		// This makes sure that the container activity has implemented
		// the callback interface. If not, it throws an exception
		try {
			mCallback = (OnOrientationConfirmedListener) activity;
		} catch (ClassCastException e) {
			throw new ClassCastException(activity.toString() + " must implement OnOrientationConfirmedListener");
		}

		initSensors();

	}

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

		View root = inflater.inflate(R.layout.orientation_check, container, false);

		ImageButton arrowImageButton = (ImageButton) root.findViewById(R.id.arrowImageButton);
		arrowImageButton.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
			
				mCallback.onOrientationConfirmed(azimuth, startTimestamp, System.currentTimeMillis());

			}
		});

		return root;

	}

	@Override
	public void onPause() {
		super.onPause();
		mSensorManager.unregisterListener(this, mSensorAccelerometer);
		mSensorManager.unregisterListener(this, mSensorMagneticField);

	}

	@Override
	public void onResume() {
		super.onResume();
		mSensorManager.registerListener(this, mSensorAccelerometer, SensorManager.SENSOR_DELAY_GAME);
		mSensorManager.registerListener(this, mSensorMagneticField, SensorManager.SENSOR_DELAY_GAME);

	}

	@Override
	public void onAccuracyChanged(Sensor sensor, int accuracy) {
	}

	@Override
	public void onSensorChanged(SensorEvent event) {

		if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
			accelData = Util.lowPass(event.values.clone(), accelData, smoothingFactor);
		}
		if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
			magnetData = Util.lowPass(event.values.clone(), magnetData, smoothingFactor);
		}

		if (accelData != null && magnetData != null) {
			float R[] = new float[9];
			float I[] = new float[9];
			boolean success = SensorManager.getRotationMatrix(R, I, accelData, magnetData);

			if (success) {
				float orientation[] = new float[3];
				SensorManager.getOrientation(R, orientation);
				azimuth = orientation[0];

			} else if (DEBUG) Log.d(TAG, "error getting rotation matrix");

		}

	}

	private void initSensors() {
		mSensorManager = (SensorManager) getActivity().getSystemService(Context.SENSOR_SERVICE);
		mSensorAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
		mSensorMagneticField = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);

		SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getActivity());
		try {
			smoothingFactor = Float.parseFloat(sp.getString(getString(R.string.key_pref_compass_smoothing), "0.01f"));
		} catch (NumberFormatException e) {
			Log.e(TAG, "Error parsing smoothing factor from preferences.");
			smoothingFactor = 0.01f;
		}

	}

}
